﻿using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Text;

namespace HouseOfTheFuture
{
    public class ControlThinkLighting : ControlThink.ZWave.ZWaveController, Lighting
    {
        object IsUpdating;
        string database;
        string Lighting.database
        {
            set
            {
                database = value;
            }
        }
        bool Lighting.Initialize()
        {
            Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\House of the Future", true);
            database = key.GetValue("database").ToString();
            key = null;
            IsUpdating = new object();
            try
            {
                //if (logLevel == 0)
                //{
                //    Console.WriteLine("Connecting to ZWave this");
                //}
                this.Connect();
                //if (logLevel < 2)
                //{
                //    Console.WriteLine("Successfully connected to ZWave this");
                //}
                for (int i = 0; i < this.Devices.Count; i++)
                {
                    //Set each ZWave device (excluding the this) to Poll and create the event handler to respond to Level changes
                    this.Devices[i].PollEnabled = true;
                    this.Devices[i].LevelChanged += new ControlThink.ZWave.Devices.ZWaveDevice.LevelChangedEventHandler(ZWaveDevice_LevelChanged);
                    //if (logLevel == 0)
                    //{
                    //    Console.WriteLine("Successfully enabled Device: " + this.Devices[i].NodeID.ToString());
                    //}
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return true;
        }
        bool Lighting.Connect()
        {
            return true;
        }

        bool Lighting.Disconnect()
        {
            if (this.IsConnected)
            {
                this.Disconnect();
            }
            return true;
        }

        int Lighting.AddDevice()
        {
            if (!this.IsConnected)
            {
                //if (logLevel < 2)
                //{
                //    Console.WriteLine("Reconnecting ZWave this");
                //}
                this.Connect();
                //if (logLevel == 0)
                //{
                //    Console.WriteLine("ZWave this reconnected successfully");
                //}
            }
            Console.WriteLine("Press the connect button on the top of the device.");
            //Process the new ZWave device
            ControlThink.ZWave.Devices.ZWaveDevice device = this.AddDevice();
            device.PollEnabled = true;
            Console.WriteLine("Node " + device.NodeID.ToString() + " added successfully");
            return device.NodeID;
            device.Dispose();
            device = null;
            
        }

        int Lighting.RemoveDevice()
        {
            if (!this.IsConnected)
            {
                //if (logLevel < 2)
                //{
                //    Console.WriteLine("Reconnecting ZWave this");
                //}
                this.Connect();
                //if (logLevel == 0)
                //{
                //    Console.WriteLine("ZWave this reconnected successfully");
                //}
            }
            Console.WriteLine("Press the connect button on the top of the device.");
            ControlThink.ZWave.Devices.ZWaveDevice device = this.RemoveDevice();
            device.PollEnabled = true;
            Console.WriteLine("Node " + device.NodeID.ToString() + " removed successfully");
            return device.NodeID;
            device.Dispose();
            device = null;

        }

        bool Lighting.UpdateDevices()
        {
            //Get the list of all light values from the database
            SQLiteConnection conn = new SQLiteConnection("Data Source=" + database);
            SQLiteDataAdapter da = new SQLiteDataAdapter("select * from light_values;", conn);
            System.Data.DataTable dt = new System.Data.DataTable();
            da.Fill(dt);
            //Check for removed Devices that are still in the database.  Remove them from the database if found
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                bool bFound = false;
                for (int j = 0; j < this.Devices.Count; j++)
                {
                    if (this.Devices[j].NodeID == (byte)int.Parse(dt.Rows[i]["node_id"].ToString()))
                    {
                        bFound = true;
                        break;
                    }
                }
                if (!bFound && this.IsConnected)
                {
                    Console.WriteLine("Removing Device: " + dt.Rows[i]["node_id"].ToString() + " from the database");
                    da = new SQLiteDataAdapter("delete from light_values where node_id = " + dt.Rows[i]["node_id"].ToString() + ";", conn);
                    da.Fill(new System.Data.DataSet());
                    //if (logLevel == 0)
                    //{
                    //    Console.WriteLine("Successfully removed Device: " + dt.Rows[i]["node_id"].ToString() + " from the database");
                    //}
                }
            }
            //Get the clean list of all light values from the database
            da = new SQLiteDataAdapter("select * from light_values;", conn);
            da.Fill(dt);
            //if (logLevel < 2)
            //{
            //    Console.WriteLine("Updating the light levels on the Devices");
            //}
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                try
                {
                    //Set the Level of the Device to what is in the database
                    this.Devices.GetByNodeID((byte)int.Parse(dt.Rows[i]["node_id"].ToString())).Level = (byte)int.Parse(dt.Rows[i]["value"].ToString());
                    //if (logLevel == 0)
                    //{
                    //    Console.WriteLine("Successfully updated Device: " + dt.Rows[i]["node_id"].ToString() + " to " + dt.Rows[i]["value"].ToString());
                    //}
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    ex = null;
                }
            }

            dt.Dispose();
            dt = null;
            da.Dispose();
            da = null;
            conn.Dispose();
            conn = null;
            return true;
        }
        /// <summary>
        /// Fires when a ZWave device level gets changed
        /// </summary>
        /// <param name="sender">ZWave Device that had its level changed</param>
        /// <param name="e">Event Args holding level change info</param>
        void ZWaveDevice_LevelChanged(object sender, ControlThink.ZWave.Devices.LevelChangedEventArgs e)
        {
            //Lock the routine so only one thread can access it
            lock (IsUpdating)
            {
                //Update the database with the new Level for this Device
                SQLiteConnection conn = new SQLiteConnection("Data Source=" + database);
                SQLiteDataAdapter da = new SQLiteDataAdapter("update light_values set value = " + e.Level + " where node_id = " + ((ControlThink.ZWave.Devices.ZWaveDevice)sender).NodeID + ";", conn);
                System.Data.DataTable dt = new System.Data.DataTable();
                //if (logLevel < 2)
                //{
                //    Console.WriteLine("Setting Device: " + ((ControlThink.ZWave.Devices.ZWaveDevice)sender).NodeID.ToString() + " to " + e.Level.ToString() + " in the database");
                //}
                da.Fill(dt);
                //if (logLevel == 0)
                //{
                //    Console.WriteLine("Update Successful");
                //}
                dt.Dispose();
                dt = null;
                da.Dispose();
                da = null;
                conn.Dispose();
                conn = null;
            }
        }
    }
}
